package com.whxd.framework.security;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.validation.AssertionImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.google.common.collect.Sets;
import com.whxd.system.user.entity.User;
import com.whxd.system.user.service.UserService;

/**
 * @author Administrator
 *
 */
public class MyAuthenticationUserDetailsServiceImpl implements
		AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {

	private final static Logger log = LoggerFactory.getLogger(MyAuthenticationUserDetailsServiceImpl.class);

	@Autowired
	private UserService userService;

	@Override
	public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
		String username = token.getName();

		User user = userService.findByUsername(username);

		if (user == null) {
			log.info("用户" + username + "不存在，创建");
			user = new User();
			user.setEnabled(true);
			// user.setCasId();//TODO 补充casid
			user.setUsername(username);
			user = userService.register(user);

			//throw new UsernameNotFoundException("用户" + username + " 不存在");
		}
		if (user.getEnabled() == false) {
			throw new DisabledException("用户已被禁用");
		}

		List<String> authorities = userService.findAuthorityNameByUsername(username);
		authorities.add("IS_LOGINED");// 手工添加已经登录标识

		Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(authorities);

		boolean enabled = user.getEnabled();
		boolean accountNonExpired = true;
		boolean credentialsNonExpired = true;
		boolean accountNonLocked = true;

		// Assertion assertion = (AssertionImpl) token.getAssertion();
		// Map<String, Object> attributes = assertion.getAttributes();
		// Iterator<Entry<String, Object>> iter =
		// attributes.entrySet().iterator();
		// while(iter.hasNext()){
		// Entry<String, Object> next = iter.next();
		// System.out.println(next.getKey()+":"+next.getValue());
		// }
		// Assertion assertion = token.getAssertion();
		// Collection<GrantedAuthority> authorities2 = token.getAuthorities();
		// Object credentials = token.getCredentials();
		// Object details = token.getDetails();
		// Object principal = token.getPrincipal();
		//

		AssertionImpl assertion = (AssertionImpl) token.getAssertion();
		AttributePrincipalImpl principal = (AttributePrincipalImpl) assertion.getPrincipal();
		Map<String, Object> attr = principal.getAttributes();

		FrameworkUserDetails userDetails = null;
		try {
			userDetails = new FrameworkUserDetails(user.getId(), (String) attr.get("id"), token.getName(),
					attr.get("sex") == null ? null : URLDecoder.decode((String) attr.get("sex"), "UTF-8"),
					attr.get("email") == null ? null : URLDecoder.decode((String) attr.get("email")),
					attr.get("address") == null ? null : URLDecoder.decode((String) attr.get("address"), "UTF-8"),
					attr.get("age") == null ? null : Integer.parseInt((String) attr.get("age")),
					attr.get("realName") == null ? null : URLDecoder.decode((String) attr.get("realName"), "UTF-8"),
					(String) attr.get("password"), (String) attr.get("mobile"), enabled, accountNonExpired,
					credentialsNonExpired, accountNonLocked, grantedAuths);
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		mergeToLocalUser(userDetails, user);

		return userDetails;
	}

	/**
	 * 更新cas中的信息到本地数据库
	 * 
	 * @param userDetails
	 * @param local
	 */
	private void mergeToLocalUser(FrameworkUserDetails userDetails, User local) {
		local.setAddress(userDetails.getAddress());
		local.setAge(userDetails.getAge());
		local.setCasId(userDetails.getCasId());
		local.setEmail(userDetails.getEmail());
		local.setMobile(userDetails.getMobile());
		local.setRealName(userDetails.getRealName());
		local.setSex(userDetails.getSex());
		userService.update(local);
	}

	/**
	 * 获得用户的角色权限.
	 */
	private Set<GrantedAuthority> obtainGrantedAuthorities(List<String> roleList) {
		Set<GrantedAuthority> authSet = Sets.newHashSet();
		if (roleList != null) {
			for (int i = 0; i < roleList.size(); i++) {
				String roleName = roleList.get(i);
				authSet.add(new GrantedAuthorityImpl(roleName));
			}
		}
		return authSet;
	}

}